package transpond

import (
    "context"
    "device-modbus/internal/biz/dao"
    "device-modbus/internal/biz/model"
    "device-modbus/internal/logic"
    "fmt"
    "log"
    "net/http"
    "net/url"
    "time"

    "github.com/cloudwego/hertz/pkg/common/json"
    "github.com/panjf2000/ants/v2"
)

type DeviceHandler struct {
    queue      *Queue
    cfgURLBase string // 例如 http://config-svc/device/
    pool       *ants.Pool
    // 设备配置缓存
    cfgCache               map[string]*dao.DeviceConfig
    deviceForwardRuleLogic *logic.DeviceForwardRuleLogic
}

func NewDeviceHandler(q *Queue, base string) *DeviceHandler {
    pool, _ := ants.NewPool(10)
    return &DeviceHandler{
        queue:                  q,
        cfgURLBase:             base,
        pool:                   pool,
        cfgCache:               make(map[string]*dao.DeviceConfig),
        deviceForwardRuleLogic: logic.NewDeviceForwardRuleLogic(context.Background()),
    }
}

// 供外部调用的入口：收到一条业务消息
func (h *DeviceHandler) onMessage(raw dao.DevicePush) {
    h.pool.Submit(func() {
        h.msg(raw)
    })
}
func (h *DeviceHandler) OnMsg(device *model.Device, data interface{}, sensorAddr string, bizTime int64, batchTime int64) {
    h.onMessage(dao.DevicePush{
        MsgId:      dao.NewID(),
        Iccid:      device.Iccid,
        Data:       data,
        SensorAddr: sensorAddr,
        BizTime:    bizTime,
        BatchTime:  batchTime,
    })
}
func (h *DeviceHandler) msg(raw dao.DevicePush) {
    cfg, err := h.fetchDeviceConfig(raw.Iccid)
    if err != nil {
        log.Printf("fetch config failed: %v", err)
        return
    }

    if len(cfg.URLs) == 0 {
        log.Printf("设备 %s 无配置", raw.Iccid)
        return
    }

    // 1. 处理序列化错误
    payload, err := json.Marshal(raw)
    if err != nil {
        log.Printf("marshal raw msg failed: %v", err)
        return
    }

    now := time.Now()
    // 2. 构建请求根据传感器地址

    for _, u := range cfg.URLs {
        if u.SensorAddr != raw.SensorAddr {
            continue
        }
        req := &PendingRequest{
            ID:     raw.MsgId + "_" + url.PathEscape(u.URL), // 2. 防特殊字符
            URL:    u.URL,
            Method: http.MethodPost,
            // 3. 构建请求头 添加utf-8 编码
            Headers:             http.Header{"Content-Type": {"application/json; charset=utf-8"}},
            Body:                payload,
            Retry:               0,
            NextTry:             now,
            Status:              "pending",
            ProcessingStartTime: now,
        }
        if u.Headers != nil {
            for k, v := range u.Headers {
                req.Headers.Set(k, v)
            }
        }
        //打印请求
        log.Printf("enqueue request: %v", req.URL)
        if err := h.queue.Enqueue(req); err != nil {
            log.Printf("enqueue failed: %v", err)
            // 3. 可选择快速失败、告警或计数
        }
    }
}

// 查询设备配置
// 从缓存中获取设备配置，如果不存在则从数据库查询并缓存
func (h *DeviceHandler) fetchDeviceConfig(iccid string) (*dao.DeviceConfig, error) {
    if cfg, ok := h.cfgCache[iccid]; ok {
        return cfg, nil
    }
    //h.RefreshDeviceConfig(iccid)
    ////判断是否存在
    //if cfg, ok := h.cfgCache[iccid]; ok {
    //    return cfg, nil
    //}
    return nil, fmt.Errorf("no config found for device %s", iccid)
}

// 刷新设备配置缓存
func (h *DeviceHandler) RefreshDeviceConfig(deviceId string, iccid string) {
    //改为数据库查询
    cfg, err := h.deviceForwardRuleLogic.FindByDeviceId(deviceId)
    if err != nil {
        log.Printf("查询设备 %s 配置失败: %v", iccid, err)
        return
    }
    if len(cfg) == 0 {
        log.Printf("设备 %s 无配置", iccid)
        return
    }
    urls := make([]dao.URLConfig, 0, len(cfg))
    for i := range cfg {
        // 过滤出有效配置
        if cfg[i].TargetURL == "" || cfg[i].SensorAddr == "" {
            continue
        }
        //判断是否存在tokenKey和tokenVal
        if cfg[i].TokenKey == "" || cfg[i].TokenVal == "" {
            //为空 默认添加tokenKey为Authorization tokenVal为Bearer
            cfg[i].TokenKey = "Authorization"
            cfg[i].TokenVal = "Bearer "
        }
        // 4. 构建URL配置
        urls = append(urls, dao.URLConfig{
            URL: cfg[i].TargetURL,
            // 5. 添加token到请求头 token Key和tokenVal不能为空
            Headers: map[string]string{
                // 6. 检查tokenKey和tokenVal是否为空
                cfg[i].TokenKey: cfg[i].TokenVal,
            },
            SensorAddr: cfg[i].SensorAddr,
        })
    }
    h.cfgCache[iccid] = &dao.DeviceConfig{
        Iccid: iccid,
        URLs:  urls,
    }
    //打印配置的数据
    log.Printf("设备 %s http配置刷新成功, 配置数量: %d", iccid, len(urls))
}
